package cn.tangshh.universal.security.config;

import cn.tangshh.universal.core.api.DR;
import cn.tangshh.universal.core.api.RCode;
import cn.tangshh.universal.core.util.JacksonUtil;
import cn.tangshh.universal.security.filter.JwtAuthorizeFilter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.PrintWriter;

/**
 * 安全配置
 *
 * @author Tang
 * @version v1.0
 * @since 2024/10/14
 */
@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {
    private final JwtAuthorizeFilter jwtFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(req -> req.requestMatchers(
                                        "/",
                                        "/swagger-ui*",
                                        "/swagger-ui/*",
                                        "/v3/api-docs*",
                                        "/v3/api-docs/*"
                                ).permitAll() // 放行我自己的登录接口和swagger接口
                                .anyRequest().authenticated()
                )
                .csrf(AbstractHttpConfigurer::disable) // 关闭跨域
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 不同过session创建管理SecurityContextHolder
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
                .exceptionHandling(configurer ->
                        configurer.authenticationEntryPoint((req, resp, ex) -> {
                            resp.setContentType("application/json; charset=utf-8");
                            PrintWriter writer = resp.getWriter();
                            writer.println(JacksonUtil.toJson(DR.of(RCode.UNAUTHORIZED)));
                        })
                );
        return http.build();
    }
}